P08-1. 통합 수집기 Grafana Alloy와 Mimir VictoriaMetrics - 이론 개념

Part 08 (이론): LGTM 메트릭 파이프라인 — 통합 수집기 Grafana Alloy와 Mimir / VictoriaMetrics

핵심 학습 목표

  1. 현대 클라우드 네이티브 관측성(Observability)의 표준인 LGTM 스택(Loki · Grafana · Tempo · Mimir/VictoriaMetrics) 에서 메트릭(Metric), 로그(Log), 트레이스(Trace) 3대 신호가 각각 어떤 역할을 맡는지 이해한다.
  2. 과거에 메트릭·로그·트레이스마다 별도로 띄우던 수집기(Prometheus Agent, Promtail, OTel Collector)를 하나로 통합한 차세대 수집기 Grafana Alloy 의 파이프라인 구조(River 문법)를 설명할 수 있다.
  3. Ambient Mesh에서 L4 TCP 메트릭은 누가 만들고(ztunnel :15020), L7 HTTP RED 메트릭은 누가 만드는지(Waypoint :15020), 그리고 외부 DB 메트릭(postgres-exporter :9187)과 어떻게 한곳(VictoriaMetrics)으로 모이는지 파악한다.
  4. 왜 평균 응답 시간(Average)에 속으면 안 되는지 이해하고, 히스토그램 버킷(_bucket, le)과 histogram_quantile(0.99, ...) 로 p99 지연 시간을 구하는 원리를 완벽히 마스터한다.


1. 왜 서비스 메시에 'LGTM 관측 스택'을 얹어야 할까?

지금까지 Part 01~07을 거치며 우리는 2세대 Ambient Mesh(ztunnel + Waypoint) 와 외부 PostgreSQL 18 하이브리드 VM(study-pg-vm) 까지 완벽하게 구축했습니다.
그리고 가장 중요한 선물을 하나 공짜로 얻었습니다. 바로 애플리케이션 코드를 단 한 줄도 고치지 않았는데, 모든 통신 길목에 서 있는 ztunnel과 Waypoint가 모든 패킷의 통행량, 응답 시간, 에러율, 보안 차단 기록을 실시간으로 측정하고 있다는 사실입니다!

하지만 이 귀중한 데이터들을 수집해서 저장하고 눈으로 볼 수 있는 관제 센터(Observability Stack) 가 없다면, 우리는 장애가 날 때마다 파드 수십 개에 일일이 kubectl logs를 쳐야 합니다.
그래서 현업에서 서비스 메시의 단짝으로 함께 구축하는 글로벌 표준 관측 아키텍처가 바로 LGTM 스택입니다!

flowchart TB
    subgraph SOURCES["1. 데이터 발생원 (Data Plane & DB)"]
        ZT["ztunnel (노드 L4 프록시)
:15020/stats/prometheus
HBONE 액세스 로그"] WP["Waypoint (네임스페이스 L7 프록시)
:15020/stats/prometheus
Envoy L7 로그 & OTLP 트레이스"] PG["study-pg-vm + postgres-exporter
:9187/metrics (Lock, Dead Tuple, Connection)"] end subgraph COLLECTOR["2. 차세대 단일 통합 수집기"] ALLOY["Grafana Alloy (v1.21.2)
Metric Scrape + Log Tail + OTLP Trace 수신을
단 하나의 에이전트 파이프라인으로 통합 처리!"] end subgraph LGTM_BACKEND["3. LGTM 저장소 및 시각화 백엔드"] M["[M] Mimir / VictoriaMetrics
시계열 메트릭 DB (PromQL)"] L["[L] Grafana Loki
라벨 기반 로그 DB (LogQL)"] T["[T] Grafana Tempo
분산 트레이스 DB (TraceQL)"] G["[G] Grafana & Kiali
Metric -> Trace -> Log 1클릭 상관분석 & 메시 토폴로지"] end ZT --> ALLOY WP --> ALLOY PG --> ALLOY ALLOY -->|"Remote Write"| M ALLOY -->|"Loki Push"| L ALLOY -->|"OTLP gRPC"| T M --> G L --> G T --> G
용어 정리 — 관측성의 3대 기둥 (3 Pillars of Observability) 과 LGTM

자동차를 운전할 때에 비유하면 3대 신호의 역할 차이가 단번에 이해됩니다:

  1. M — Metric (메트릭 = 자동차 계기판 경고등, Part 08):
    • 저장소: Grafana Mimir 또는 VictoriaMetrics (Prometheus 호환 시계열 DB)
    • 역할: "16시 30분부터 order-api의 에러율이 15%로 치솟았고, 99번째로 느린 응답 시간(p99)이 3.2초입니다!" 처럼 숫자로 집계된 상태 변화와 이상 징후를 가장 먼저 알려주는 계기판입니다.
  2. T — Trace (트레이스 = 병원 전신 엑스레이/내시경, Part 10):
    • 저장소: Grafana Tempo
    • 역할: 계기판에 "응답 시간 3.2초!" 경고등이 켜졌을 때, 고객의 요청 1건이 지나간 전체 경로(study-client → ztunnel → Waypoint → order-api → PostgreSQL) 중 도대체 어느 구간에서 3.19초를 잡아먹었는지 바코드(Trace ID) 하나로 끝까지 추적해 주는 내시경입니다.
  3. L — Log (로그 = 항공기 블랙박스 음성 기록, Part 09):
    • 저장소: Grafana Loki
    • 역할: 문제가 발생한 바로 그 시각, 그 파드에서 정확히 무슨 일이 있었는지(RBAC: access denied, reset reason: overflow (UO), PostgreSQL deadlock) 상세한 텍스트 정황 증거를 남기는 블랙박스입니다.
  4. G — Grafana (그라파나, Part 11):
    • 위 L · T · M 세 가지 저장소를 하나의 화면에 모아, 메트릭 그래프의 뾰족한 장애 지점을 클릭하면 → 즉시 해당 요청의 트레이스(Tempo)와 로그(Loki)로 1초 만에 점프(Correlation) 할 수 있게 해주는 통합 관제 대시보드입니다.

2. 왜 Grafana Alloy인가? (수집기 춘추전국시대의 종결자)

불과 1~2년 전까지만 해도 쿠버네티스 클러스터에 관측 시스템을 구축하려면 워커 노드마다 서로 다른 3개의 수집기 에이전트를 따로따로 설치해야 했습니다:

설정도 제각각이고 메모리도 3배로 먹던 이 파편화를 끝내기 위해 Grafana Labs가 공식 출시한 차세대 통합 수집기가 바로 Grafana Alloy 입니다! (참고로 기존 Promtail과 Grafana Agent는 공식적으로 수명이 종료되어 모두 Grafana Alloy 로 통합되었습니다.)

용어 정리 — Grafana Alloy 와 River 파이프라인 문법

  • Grafana Alloy: 단 1개의 프로그램(파드) 안에서 Prometheus 메트릭 수집(prometheus.scrape), Loki 로그 수집(loki.source.kubernetes), OpenTelemetry 트레이스 수신(otelcol.receiver.otlp)을 모두 처리하는 올인원 수집기입니다.
  • Alloy 설정 문법 (구 River 문법):
    들여쓰기 실수가 잦은 YAML 대신, Terraform(HCL)과 아주 비슷한 블록 형태로 데이터의 흐름(발견 → 수집 → 가공 → 전송)을 레고 블록 조립하듯 연결합니다.
    // 1단계: 어디서 긁어올지(Scrape) 정의하고 다음 단계(forward_to)로 토스!
    prometheus.scrape "mesh_metrics" {
      targets    = [ ... ]
      forward_to = [prometheus.remote_write.vmsingle.receiver]
    }
    
    // 2단계: 받은 메트릭을 저장소(VictoriaMetrics / Mimir)로 전송(Remote Write)!
    prometheus.remote_write "vmsingle" {
      endpoint {
        url = "http://vmsingle.monitoring.svc:8428/api/v1/write"
      }
    }
    
    코드만 읽어도 데이터가 어디서 출발해(prometheus.scrape) 어디로 흘러가는지(forward_to -> prometheus.remote_write) 화살표처럼 한눈에 보입니다!

왜 실습 백엔드로 VictoriaMetrics (v1.154.1)를 함께 쓰나요?

Grafana Mimir와 VictoriaMetrics는 현재 엔터프라이즈 시장에서 가장 널리 쓰이는 양대 고성능 시계열 DB(TSDB)이며, 두 엔진 모두 Prometheus의 데이터 수집 규격(Remote Write)과 쿼리 언어(PromQL)를 100% 똑같이 지원합니다.
특히 단일 노드(vmsingle)로 구동되는 VictoriaMetrics는 일반 Prometheus나 Mimir 대비 메모리 사용량이 1/4 수준(수십 MB)이면서도 쿼리 속도가 압도적으로 빨라, 로컬 3노드 클러스터부터 대규모 멀티 클라우드 관제까지 김수종 책임님의 핵심 기술 스택으로 완벽히 부합합니다.


3. Ambient Mesh의 3대 핵심 메트릭 출처 해부

Grafana Alloy가 우리 클러스터에서 긁어모을 메트릭은 크게 3곳에서 나옵니다.

수집 대상 열려 있는 포트 및 경로 주요 생성 메트릭 이름 무엇을 알려주나요?
1. ztunnel (노드 L4 프록시) :15020/stats/prometheus istio_tcp_sent_bytes_total
istio_tcp_received_bytes_total
istio_tcp_connections_opened_total
istio_tcp_connections_closed_total
Waypoint가 없는 순수 L4 상태에서도 누가(source_workload) 누구(destination_workload)에게 몇 바이트의 암호화 패킷을 보냈고 연결을 몇 번 맺었는지 100% 기록!
2. Waypoint Proxy (네임스페이스 L7 프록시) :15020/stats/prometheus istio_requests_total
istio_request_duration_milliseconds_bucket
HTTP 상태 코드(200, 403, 500, 503), Envoy 응답 플래그(UO, NR), 서비스/버전별 요청 횟수와 정확한 응답 지연 시간 분포(Histogram) 기록!
3. postgres-exporter (외부 PG 18 VM 연결) :9187/metrics pg_up
pg_stat_activity_count
pg_locks_count
pg_stat_user_tables_n_dead_tup
외부 Linux VM(study-pg-vm)의 현재 활성 커넥션 수, 잠금(Lock) 대기 개수, 테이블별 죽은 튜플(Dead Tuple) 개수를 실시간 노출!

4. 초보자가 가장 헷갈리는 개념 정복: 히스토그램 버킷(_bucket, le)과 p99 지연 시간

모니터링 대시보드를 만들 때 가장 흔히 저지르는 실수가 바로 "평균 응답 시간(Average Latency)" 만 쳐다보는 것입니다.

4-1. 왜 '평균(Average)'에 속으면 안 될까요?

어떤 쇼핑몰에 100명의 고객이 접속했습니다.

평균 그래프만 보면 "어? 평균 0.1초네! 서버 아주 빠르고 평화롭군!" 이라고 착각하게 됩니다. 하지만 실제로는 결제 고객의 1%가 10초씩 멈추는 대형 장애가 나고 있는 것입니다!

그래서 실무 SRE에서는 평균 대신 "응답 시간을 가장 빠른 순서대로 1번부터 100번까지 줄 세웠을 때, 맨 뒤에서 95번째(p95) 또는 99번째(p99)로 느린 사람의 응답 시간이 얼마인가?" 를 뜻하는 백분위수(Percentile) 를 표준 지표로 사용합니다!

4-2. Envoy와 Prometheus는 어떻게 p99를 계산할까요? (_bucket과 le 바구니!)

수백만 건의 요청 시간을 일일이 다 저장해서 줄 세우려면 메모리가 터져버립니다.
그래서 Envoy(Waypoint)는 미리 시간대별 크기 바구니(Bucket) 를 여러 개 준비해 두고, 요청이 끝날 때마다 해당되는 바구니에 공(카운트)을 1개씩 던져 넣습니다! 이 지표를 히스토그램(Histogram) 이라고 부릅니다.

flowchart LR
    REQ["요청 1건 처리 완료!
(걸린 시간: 35ms)"] --> B5["바구니 1 (le='5')
5ms 이하인가? (X)"] REQ --> B10["바구니 2 (le='10')
10ms 이하인가? (X)"] REQ --> B25["바구니 3 (le='25')
25ms 이하인가? (X)"] REQ --> B50["바구니 4 (le='50')
50ms 이하인가? (O! +1 증가)"] REQ --> B100["바구니 5 (le='100')
100ms 이하인가? (O! +1 증가)"] REQ --> BINF["마지막 바구니 (le='+Inf')
무한대 이하인가? (O! +1 증가)"]
용어 정리 — _bucket, le, 그리고 histogram_quantile 공식

  1. le (Less than or Equal to, ~이하):
    • 히스토그램 메트릭(istio_request_duration_milliseconds_bucket)에 항상 붙어 다니는 라벨입니다.
    • 예를 들어 le="50" 바구니의 숫자가 180이라는 뜻은 "응답 시간이 50밀리초 이하(0ms ~ 50ms 사이)로 걸린 요청이 총 180건 있었다" 는 뜻입니다(누적 바구니이므로 35ms 걸린 요청은 le="50", le="100", le="500", le="+Inf" 바구니에 모두 포함됩니다).
  2. RED 3대 황금 PromQL 쿼리 (외워두면 평생 쓰는 실무 공식!):
    • R (Rate — 초당 요청 수, RPS):
      sum(rate(istio_requests_total[1m])) by (destination_service_name)
    • E (Errors — 초당 5xx/4xx 에러 발생 수):
      sum(rate(istio_requests_total{response_code=~"5.."}[1m])) by (destination_service_name, response_flags)
    • D (Duration — 상위 99% 지연 시간, p99 Latency):
      histogram_quantile(0.99, sum(rate(istio_request_duration_milliseconds_bucket[1m])) by (le, destination_service_name))
      (핵심 주의점: histogram_quantile을 쓸 때는 바구니 구분자인 by (le) 를 절대 빼먹으면 안 됩니다!)


🔗 다음 단계 (실습 검증)

이론으로 배운 LGTM의 첫 번째 기둥을 이제 우리의 docker-desktop 클러스터에 직접 세워 봅니다!

  1. 관측 전용 네임스페이스(monitoring)를 만들고, 초고속 TSDB인 VictoriaMetrics (v1.154.1) 와 외부 PostgreSQL 18 VM을 감시하는 postgres-exporter, 그리고 통합 수집기인 Grafana Alloy (v1.21.2) 를 배포합니다.
  2. order-api와 외부 DB(pg-vm.mesh.internal)에 트래픽을 발생시킨 뒤,
  3. VictoriaMetrics의 PromQL API에 직접 쿼리를 날려 ztunnel의 L4 바이트 메트릭, Waypoint의 L7 RED 메트릭(p99 응답 시간 포함), 그리고 외부 PostgreSQL 18 VM의 실시간 세션/Lock 메트릭이 한곳에서 조회되는 것을 100% 실측합니다!

네비게이션

이전 목록 다음
◀ Part 07 실습 목록으로 Part 08 실습 ▶